#pragma once
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <string>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <functional>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "./tcp_reactor/tcp_reactor.hh"
#include "thread_pool.hh"
using namespace std;
class http_server_t
{
    /*
    ** Transport (传输层):
    **  见tcp_reactor.hh
    */

public:
    http_server_t(int port)
        : _tcp_reactor(std::bind(&http_server_t::request_handler, this, placeholders::_1, placeholders::_2), std::bind(&http_server_t::package_split, this, placeholders::_1, placeholders::_2), port),
          _www_root("wwwroot"), _home_page("index.html")
    {
        ;
    };
    void set_home_page(string_view path = "index.html")
    {
        _home_page = path;
    }
    void set_base_dir(string_view dir = "./wwwroot")
    {
        _www_root = dir;
        if (_www_root.back() == '/')
            _www_root.pop_back();
    }
    // client -> reactor recv ->thread_pool->httpserver->reactor send
    void run()
    {
        _p_thread_pool = thread_pool_t<request, response>::get_thread_pool_instance(std::bind(&http_server_t::http_service, this, placeholders::_1, placeholders::_2));
        _p_thread_pool->start();
        pthread_t pid;
        // reactor
        pthread_create(&pid, nullptr, response_handler, static_cast<void *>(this));
        while (1)
        {
            _tcp_reactor.run();
        }
    }

private:
    static void *response_handler(void *arg)
    {
        pthread_detach(pthread_self());
        http_server_t *p_this = static_cast<http_server_t *>(arg);
        while (1)
        {
            response rsp;
            p_this->_p_thread_pool->get_rsp(rsp);
            if (!p_this->_tcp_reactor.is_con_exist(rsp._p_con))
            {
                log(INFO, "p_con not exists");
                continue;
            }
            // 序列化后发送给客户端
            string package;
            if (p_this->serialize(rsp, package))
            {
                rsp._p_con->_sendfile_fd = rsp._file_fd;
                rsp._p_con->_file_size = rsp._file_size;
                rsp._p_con->_out_buffer.append(package);
                if (!(rsp._p_con->get_events() & EPOLLOUT))
                {
                    rsp._p_con->get_server()->add_write_care(rsp._p_con);
                }
            }
            // 线程池->reactor write事件
            else
            {
                if (rsp._p_con->is_func_exist_error())
                    rsp._p_con->error_handler();
            }
            continue;
        }
        log(FATAL, "thread dead!");
        return nullptr;
    }
    /*
    ** protocol(协议层):
    **
    ** 此处定义了http协议相关的数据和方法:
    **  包含: http请求结构与响应结构;
    **        报文分割,序列与反序列化方法;
    */
public:
    struct request
    {
        request(connection_t *p_con = nullptr) : _p_con(p_con) { ; }
        // reactor_connection
        connection_t *_p_con;
        // 请求方法
        string _method = "";
        // uri
        string _path = "";
        // 参数
        string _query_str = "";
        string _version = "";
        // 首部kv
        unordered_map<string, string> _request_handers{};
        // 正文
        string _body = "";
        bool cgi = false;
    };

    struct response
    {
        response(connection_t *p_con = nullptr) : _p_con(p_con)
        {
            ;
        }
        ~response()
        {
            ;
        }
        // reactor_connection
        connection_t *_p_con;
        // status_line;
        string _version = "";
        string _code = "";
        string _status_info = "";
        // kv
        unordered_map<string, string> _reponse_handers{};
        // body
        string _body = "";
        // file
        int _file_fd = -1;
        size_t _file_size = 0;
    };

private:
    const char *SEP = "\r\n\r\n";
    const char *CRLF = "\r\n";

    bool package_split(string &input, vector<string> &result)
    {
        while (true)
        {
            if (input.empty())
                break;
            // 检查是否为有效的 HTTP 方法
            static unordered_set<string> methods = {"GET", "POST", "DELETE"};
            size_t method_end = input.find(' ');
            if (method_end == std::string::npos ||
                methods.find(input.substr(0, method_end)) == methods.end())
            {
                log(INFO, "method not legitimate");
                return false;
            }
            // 获取请求头，以 "/r/n/r/n" 为分隔符
            int sep_pos = input.find(SEP);
            if (sep_pos == std::string::npos)
            {
                break;
            }
            // 提取请求头部
            std::string req_header = input.substr(0, sep_pos + 4);
            // 解析 Content-Length
            int content_length = 0;
            int pos_begin = req_header.find("Content-Length:");
            // 如果有正文 读取正文
            if (pos_begin != std::string::npos)
            {
                size_t num_end = req_header.find(CRLF, pos_begin);
                size_t num_begin = pos_begin + strlen("Content-Length: ");
                // cout << "input:" << input;
                try
                {
                    content_length = std::stoi(req_header.substr(num_begin, num_end - num_begin));
                    if (content_length < 0)
                    {
                        throw;
                    }
                    log(INFO, "content-length:" + to_string(content_length));
                }
                catch (const std::exception &e)
                {
                    log(ERROR, string("Content-Length is not valid :") + e.what());
                    return false;
                }
                if (input.size() < req_header.size() + content_length)
                {
                    log(INFO, string("size not enough cur:") + to_string(input.size() - req_header.size()));
                    break;
                }
                // 提取正文
                log(INFO, string("cursize:") + to_string(input.size() - req_header.size()));
                req_header += input.substr(sep_pos + strlen(SEP), content_length);
            }
            // 添加到结果集
            // cout << "result:" << req_header << endl;
            result.push_back(std::move(req_header));
            // 删除已处理的部分
            input.erase(0, sep_pos + strlen(SEP) + content_length);
        }

        return true;
    }
    bool parse_head_kv(unordered_map<string, string> &u_map, string kv_str)
    {
        try
        {
            while (true)
            {
                // 提取一行
                int line_end_pos = kv_str.find(CRLF);
                if (line_end_pos == string::npos)
                    return true;
                string line = kv_str.substr(0, line_end_pos);
                int sep_pos = kv_str.find(": ");
                if (sep_pos == string::npos)
                    return false;
                string key = line.substr(0, sep_pos);
                string value = line.substr(sep_pos + 2);
                kv_str.erase(0, line_end_pos + strlen(CRLF));
                // log(INFO, string(key) + "-:-" + string(value));
                u_map[key] = value;
            }
        }
        catch (const std::exception &e)
        {
            log(ERROR, string("throwed: ") + e.what());
            return false;
        }
        return true;
    }
    bool deserialize(string_view package, request &req)
    {
        try
        {
            // 首行信息
            int first_line_end = package.find(CRLF);
            stringstream first_line(package.substr(0, first_line_end).data());
            string uri_str;
            first_line >> req._method >> uri_str >> req._version;
            // url解码
            uri_str = urlDecode(uri_str);
            // 提取参数
            size_t query_pos = uri_str.find('?');
            if (query_pos != string::npos)
                req._query_str = uri_str.substr(query_pos + 1);
            req._path = _www_root + uri_str.substr(0, query_pos);
            if (req._path.back() == '/')
                req._path += _home_page;
            // 首部
            int kv_line_end = package.find(SEP);
            string kv_string = package.substr(first_line_end + strlen(CRLF), kv_line_end + strlen(CRLF)).data();
            parse_head_kv(req._request_handers, kv_string);
            // 正文
            req._body = package.substr(kv_line_end + strlen(SEP));
            log(INFO, string(req._path));
        }
        catch (const std::exception &e)
        {
            log(ERROR, string("throwed: ") + e.what());
            return false;
        }
        return true;
    }
    bool serialize(const response &res, string &package)
    {
        log(INFO, "start serialize");
        package.clear();
        package += res._version + ' ' + res._code + ' ' + res._status_info + CRLF;
        // cgi has kv in body
        if (!res._reponse_handers.empty())
        {
            for (auto e : res._reponse_handers)
            {
                package += e.first + ": " + e.second + CRLF;
            }
            package += CRLF;
        }
        package += res._body;
        log(INFO, "serialize done");
        return true;
    }
    static string ext_to_type(string_view str)
    {
        static unordered_map<string_view, const string> desc_map{{".tif", "image/tiff"},
                                                                 {".001", "application/x-001"},
                                                                 {".301", "application/x-301"},
                                                                 {".323", "text/h323"},
                                                                 {".906", "application/x-906"},
                                                                 {".907", "drawing/907"},
                                                                 {".a11", "application/x-a11"},
                                                                 {".acp", "audio/x-mei-aac"},
                                                                 {".ai", "application/postscript"},
                                                                 {".aif", "audio/aiff"},
                                                                 {".aifc", "audio/aiff"},
                                                                 {".aiff", "audio/aiff"},
                                                                 {".anv", "application/x-anv"},
                                                                 {".asa", "text/asa"},
                                                                 {".asf", "video/x-ms-asf"},
                                                                 {".asp", "text/asp"},
                                                                 {".asx", "video/x-ms-asf"},
                                                                 {".au", "audio/basic"},
                                                                 {".avi", "video/avi"},
                                                                 {".awf", "application/vnd.adobe.workflow"},
                                                                 {".biz", "text/xml"},
                                                                 {".bmp", "application/x-bmp"},
                                                                 {".bot", "application/x-bot"},
                                                                 {".c4t", "application/x-c4t"},
                                                                 {".c90", "application/x-c90"},
                                                                 {".cal", "application/x-cals"},
                                                                 {".cat", "application/vnd.ms-pki.seccat"},
                                                                 {".cdf", "application/x-netcdf"},
                                                                 {".cdr", "application/x-cdr"},
                                                                 {".cel", "application/x-cel"},
                                                                 {".cer", "application/x-x509-ca-cert"},
                                                                 {".cg4", "application/x-g4"},
                                                                 {".cgm", "application/x-cgm"},
                                                                 {".cit", "application/x-cit"},
                                                                 {".class", "java/*"},
                                                                 {".cml", "text/xml"},
                                                                 {".cmp", "application/x-cmp"},
                                                                 {".cmx", "application/x-cmx"},
                                                                 {".cot", "application/x-cot"},
                                                                 {".crl", "application/pkix-crl"},
                                                                 {".crt", "application/x-x509-ca-cert"},
                                                                 {".csi", "application/x-csi"},
                                                                 {".css", "text/css"},
                                                                 {".cut", "application/x-cut"},
                                                                 {".dbf", "application/x-dbf"},
                                                                 {".dbm", "application/x-dbm"},
                                                                 {".dbx", "application/x-dbx"},
                                                                 {".dcd", "text/xml"},
                                                                 {".dcx", "application/x-dcx"},
                                                                 {".der", "application/x-x509-ca-cert"},
                                                                 {".dgn", "application/x-dgn"},
                                                                 {".dib", "application/x-dib"},
                                                                 {".dll", "application/x-msdownload"},
                                                                 {".doc", "application/msword"},
                                                                 {".dot", "application/msword"},
                                                                 {".drw", "application/x-drw"},
                                                                 {".dtd", "text/xml"},
                                                                 {".dwf", "Model/vnd.dwf"},
                                                                 {".dwf", "application/x-dwf"},
                                                                 {".dwg", "application/x-dwg"},
                                                                 {".dxb", "application/x-dxb"},
                                                                 {".dxf", "application/x-dxf"},
                                                                 {".edn", "application/vnd.adobe.edn"},
                                                                 {".emf", "application/x-emf"},
                                                                 {".eml", "message/rfc822"},
                                                                 {".ent", "text/xml"},
                                                                 {".epi", "application/x-epi"},
                                                                 {".eps", "application/x-ps"},
                                                                 {".eps", "application/postscript"},
                                                                 {".etd", "application/x-ebx"},
                                                                 {".exe", "application/x-msdownload"},
                                                                 {".fax", "image/fax"},
                                                                 {".fdf", "application/vnd.fdf"},
                                                                 {".fif", "application/fractals"},
                                                                 {".fo", "text/xml"},
                                                                 {".frm", "application/x-frm"},
                                                                 {".g4", "application/x-g4"},
                                                                 {".gbr", "application/x-gbr"},
                                                                 {".", "application/x-"},
                                                                 {".gif", "image/gif"},
                                                                 {".gl2", "application/x-gl2"},
                                                                 {".gp4", "application/x-gp4"},
                                                                 {".hgl", "application/x-hgl"},
                                                                 {".hmr", "application/x-hmr"},
                                                                 {".hpg", "application/x-hpgl"},
                                                                 {".hpl", "application/x-hpl"},
                                                                 {".hqx", "application/mac-binhex40"},
                                                                 {".hrf", "application/x-hrf"},
                                                                 {".hta", "application/hta"},
                                                                 {".htc", "text/x-component"},
                                                                 {".htm", "text/html"},
                                                                 {".html", "text/html"},
                                                                 {".htt", "text/webviewhtml"},
                                                                 {".htx", "text/html"},
                                                                 {".icb", "application/x-icb"},
                                                                 {".ico", "image/x-icon"},
                                                                 {".ico", "application/x-ico"},
                                                                 {".iff", "application/x-iff"},
                                                                 {".ig4", "application/x-g4"},
                                                                 {".igs", "application/x-igs"},
                                                                 {".iii", "application/x-iphone"},
                                                                 {".img", "application/x-img"},
                                                                 {".ins", "application/x-internet-signup"},
                                                                 {".isp", "application/x-internet-signup"},
                                                                 {".IVF", "video/x-ivf"},
                                                                 {".java", "java/*"},
                                                                 {".jfif", "image/jpeg"},
                                                                 {".jpe", "image/jpeg"},
                                                                 {".jpe", "application/x-jpe"},
                                                                 {".jpeg", "image/jpeg"},
                                                                 {".jpg", "image/jpeg"},
                                                                 {".jpg", "application/x-jpg"},
                                                                 {".js", "application/x-javascript"},
                                                                 {".json", "application/json"},
                                                                 {".jsp", "text/html"},
                                                                 {".la1", "audio/x-liquid-file"},
                                                                 {".lar", "application/x-laplayer-reg"},
                                                                 {".latex", "application/x-latex"},
                                                                 {".lavs", "audio/x-liquid-secure"},
                                                                 {".lbm", "application/x-lbm"},
                                                                 {".lmsff", "audio/x-la-lms"},
                                                                 {".ls", "application/x-javascript"},
                                                                 {".ltr", "application/x-ltr"},
                                                                 {".m1v", "video/x-mpeg"},
                                                                 {".m2v", "video/x-mpeg"},
                                                                 {".m3u", "audio/mpegurl"},
                                                                 {".m3u8", "application/x-mpegURL"},
                                                                 {".m4e", "video/mpeg4"},
                                                                 {".mac", "application/x-mac"},
                                                                 {".man", "application/x-troff-man"},
                                                                 {".math", "text/xml"},
                                                                 {".mdb", "application/msaccess"},
                                                                 {".mdb", "application/x-mdb"},
                                                                 {".mfp", "application/x-shockwave-flash"},
                                                                 {".mht", "message/rfc822"},
                                                                 {".mhtml", "message/rfc822"},
                                                                 {".mi", "application/x-mi"},
                                                                 {".mid", "audio/mid"},
                                                                 {".midi", "audio/mid"},
                                                                 {".mil", "application/x-mil"},
                                                                 {".mml", "text/xml"},
                                                                 {".mnd", "audio/x-musicnet-download"},
                                                                 {".mns", "audio/x-musicnet-stream"},
                                                                 {".mocha", "application/x-javascript"},
                                                                 {".movie", "video/x-sgi-movie"},
                                                                 {".mp1", "audio/mp1"},
                                                                 {".mp2", "audio/mp2"},
                                                                 {".mp2v", "video/mpeg"},
                                                                 {".mp3", "audio/mp3"},
                                                                 {".mp4", "video/mpeg4"},
                                                                 {".mpa", "video/x-mpg"},
                                                                 {".mpd", "application/vnd.ms-project"},
                                                                 {".mpe", "video/x-mpeg"},
                                                                 {".mpeg", "video/mpg"},
                                                                 {".mpg", "video/mpg"},
                                                                 {".mpga", "audio/rn-mpeg"},
                                                                 {".mpp", "application/vnd.ms-project"},
                                                                 {".mps", "video/x-mpeg"},
                                                                 {".mpt", "application/vnd.ms-project"},
                                                                 {".mpv", "video/mpg"},
                                                                 {".mpv2", "video/mpeg"},
                                                                 {".mpw", "application/vnd.ms-project"},
                                                                 {".mpx", "application/vnd.ms-project"},
                                                                 {".mtx", "text/xml"},
                                                                 {".mxp", "application/x-mmxp"},
                                                                 {".net", "image/pnetvue"},
                                                                 {".nrf", "application/x-nrf"},
                                                                 {".nws", "message/rfc822"},
                                                                 {".odc", "text/x-ms-odc"},
                                                                 {".out", "application/x-out"},
                                                                 {".p10", "application/pkcs10"},
                                                                 {".p12", "application/x-pkcs12"},
                                                                 {".p7b", "application/x-pkcs7-certificates"},
                                                                 {".p7c", "application/pkcs7-mime"},
                                                                 {".p7m", "application/pkcs7-mime"},
                                                                 {".p7r", "application/x-pkcs7-certreqresp"},
                                                                 {".p7s", "application/pkc"},
                                                                 {".pc5", "application/x-pc5"},
                                                                 {".pci", "application/x-pci"},
                                                                 {".pcl", "application/x-pcl"},
                                                                 {".pcx", "application/x-pcx"},
                                                                 {".pdf", "application/pdf"},
                                                                 {".pdx", "application/vnd.adobe.pdx"},
                                                                 {".pfx", "application/x-pkcs12"},
                                                                 {".pgl", "application/x-pgl"},
                                                                 {".pic", "application/x-pic"},
                                                                 {".pko", "application/vnd.ms-pki.pko"},
                                                                 {".pl", "application/x-perl"},
                                                                 {".plg", "text/html"},
                                                                 {".pls", "audio/scpls"},
                                                                 {".plt", "application/x-plt"},
                                                                 {".png", "image/png"},
                                                                 {".pot", "application/vnd.ms-powerpoint"},
                                                                 {".ppa", "application/vnd.ms-powerpoint"},
                                                                 {".ppm", "application/x-ppm"},
                                                                 {".pps", "application/vnd.ms-powerpoint"},
                                                                 {".ppt", "application/vnd.ms-powerpoint"},
                                                                 {".pr", "application/x-pr"},
                                                                 {".prf", "application/pics-rules"},
                                                                 {".prn", "application/x-prn"},
                                                                 {".prt", "application/x-prt"},
                                                                 {".ps", "application/x-ps"},
                                                                 {".ptn", "application/x-ptn"},
                                                                 {".pwz", "application/vnd.ms-powerpoint"},
                                                                 {".r3t", "text/vnd.rn-realtext3d"},
                                                                 {".ra", "audio/vnd.rn-realaudio"},
                                                                 {".ram", "audio/x-pn-realaudio"},
                                                                 {".ras", "application/x-ras"},
                                                                 {".rat", "application/rat-file"},
                                                                 {".rdf", "text/xml"},
                                                                 {".rec", "application/vnd.rn-recording"},
                                                                 {".red", "application/x-red"},
                                                                 {".rgb", "application/x-rgb"},
                                                                 {".rjs", "application/vnd.rn-realsystem-rjs"},
                                                                 {".rjt", "application/vnd.rn-realsystem-rjt"},
                                                                 {".rlc", "application/x-rlc"},
                                                                 {".rle", "application/x-rle"},
                                                                 {".rm", "application/vnd.rn-realmedia"},
                                                                 {".rmf", "application/vnd.adobe.rmf"},
                                                                 {".rmi", "audio/mid"},
                                                                 {".rmj", "application/vnd.rn-realsystem-rmj"},
                                                                 {".rmm", "audio/x-pn-realaudio"},
                                                                 {".rmp", "application/vnd.rn-rnmusicpackage"},
                                                                 {".rms", "application/vnd.rn-realmedia-secure"},
                                                                 {".rmvb", "application/vnd.rn-realmedia-vbr"},
                                                                 {".rmx", "application/vnd.rn-realsystem-rmx"},
                                                                 {".rnx", "application/vnd.rn-realplayer"},
                                                                 {".rp", "image/vnd.rn-realpix"},
                                                                 {".rpm", "audio/x-pn-realaudio-plugin"},
                                                                 {".rsml", "application/vnd.rn-rsml"},
                                                                 {".rt", "text/vnd.rn-realtext"},
                                                                 {".rtf", "application/msword"},
                                                                 {".rv", "video/vnd.rn-realvideo"},
                                                                 {".sam", "application/x-sam"},
                                                                 {".sat", "application/x-sat"},
                                                                 {".sdp", "application/sdp"},
                                                                 {".sdw", "application/x-sdw"},
                                                                 {".sit", "application/x-stuffit"},
                                                                 {".slb", "application/x-slb"},
                                                                 {".sld", "application/x-sld"},
                                                                 {".slk", "drawing/x-slk"},
                                                                 {".smi", "application/smil"},
                                                                 {".smil", "application/smil"},
                                                                 {".smk", "application/x-smk"},
                                                                 {".snd", "audio/basic"},
                                                                 {".sol", "text/plain"},
                                                                 {".sor", "text/plain"},
                                                                 {".spc", "application/x-pkcs7-certificates"},
                                                                 {".spl", "application/futuresplash"},
                                                                 {".spp", "text/xml"},
                                                                 {".ssm", "application/streamingmedia"},
                                                                 {".sst", "application/vnd.ms-pki.certstore"},
                                                                 {".stl", "application/vnd.ms-pki.stl"},
                                                                 {".stm", "text/html"},
                                                                 {".sty", "application/x-sty"},
                                                                 {".svg", "text/xml"},
                                                                 {".swf", "application/x-shockwave-flash"},
                                                                 {".tdf", "application/x-tdf"},
                                                                 {".tg4", "application/x-tg4"},
                                                                 {".tga", "application/x-tga"},
                                                                 {".tif", "image/tiff"},
                                                                 {".tif", "application/x-tif"},
                                                                 {".tiff", "image/tiff"},
                                                                 {".tld", "text/xml"},
                                                                 {".top", "drawing/x-top"},
                                                                 {".torrent", "application/x-bittorrent"},
                                                                 {".ts", "video/MP2T"},
                                                                 {".tsd", "text/xml"},
                                                                 {".txt", "text/plain"},
                                                                 {".uin", "application/x-icq"},
                                                                 {".uls", "text/iuls"},
                                                                 {".vcf", "text/x-vcard"},
                                                                 {".vda", "application/x-vda"},
                                                                 {".vdx", "application/vnd.visio"},
                                                                 {".vml", "text/xml"},
                                                                 {".vpg", "application/x-vpeg005"},
                                                                 {".vsd", "application/vnd.visio"},
                                                                 {".vsd", "application/x-vsd"},
                                                                 {".vss", "application/vnd.visio"},
                                                                 {".vst", "application/vnd.visio"},
                                                                 {".vst", "application/x-vst"},
                                                                 {".vsw", "application/vnd.visio"},
                                                                 {".vsx", "application/vnd.visio"},
                                                                 {".vtx", "application/vnd.visio"},
                                                                 {".vxml", "text/xml"},
                                                                 {".wav", "audio/wav"},
                                                                 {".wax", "audio/x-ms-wax"},
                                                                 {".wb1", "application/x-wb1"},
                                                                 {".wb2", "application/x-wb2"},
                                                                 {".wb3", "application/x-wb3"},
                                                                 {".wbmp", "image/vnd.wap.wbmp"},
                                                                 {".wiz", "application/msword"},
                                                                 {".wk3", "application/x-wk3"},
                                                                 {".wk4", "application/x-wk4"},
                                                                 {".wkq", "application/x-wkq"},
                                                                 {".wks", "application/x-wks"},
                                                                 {".wm", "video/x-ms-wm"},
                                                                 {".wma", "audio/x-ms-wma"},
                                                                 {".wmd", "application/x-ms-wmd"},
                                                                 {".wmf", "application/x-wmf"},
                                                                 {".wml", "text/vnd.wap.wml"},
                                                                 {".wmv", "video/x-ms-wmv"},
                                                                 {".wmx", "video/x-ms-wmx"},
                                                                 {".wmz", "application/x-ms-wmz"},
                                                                 {".wp6", "application/x-wp6"},
                                                                 {".wpd", "application/x-wpd"},
                                                                 {".wpg", "application/x-wpg"},
                                                                 {".wpl", "application/vnd.ms-wpl"},
                                                                 {".wq1", "application/x-wq1"},
                                                                 {".wr1", "application/x-wr1"},
                                                                 {".wri", "application/x-wri"},
                                                                 {".wrk", "application/x-wrk"},
                                                                 {".ws", "application/x-ws"},
                                                                 {".ws2", "application/x-ws"},
                                                                 {".wsc", "text/scriptlet"},
                                                                 {".wsdl", "text/xml"},
                                                                 {".wvx", "video/x-ms-wvx"},
                                                                 {".xdp", "application/vnd.adobe.xdp"},
                                                                 {".xdr", "text/xml"},
                                                                 {".xfd", "application/vnd.adobe.xfd"},
                                                                 {".xfdf", "application/vnd.adobe.xfdf"},
                                                                 {".xhtml", "text/html"},
                                                                 {".xls", "application/vnd.ms-excel"},
                                                                 {".xls", "application/x-xls"},
                                                                 {".xlw", "application/x-xlw"},
                                                                 {".xml", "text/xml"},
                                                                 {".xpl", "audio/scpls"}};
        auto it = desc_map.find(str);
        if (it == desc_map.end())
        {
            // 如果找不到，返回默认值
            return desc_map[string_view(".html")];
        }
        return it->second;
    }
    static string code_to_info(string_view code)
    {
        // 状态码 描述
        static unordered_map<string_view, const string> info_map{
            {"200", "OK"},
            {"201", "Created"},
            {"301", "Moved Permanently"},
            {"302", "Found"},
            {"400", "Bad Request"},
            {"401", "Unauthorized"},
            {"403", "Forbidden"},
            {"404", "Not Found"},
            {"500", "Internal Server Error"},
            {"503", "Service Unavailable"}};
        auto it = info_map.find(code);
        if (it != info_map.end())
        {
            return it->second;
        }
        else
        {
            // 处理未知状态码的情况，这里选择返回一个默认描述
            return "Unknown Status Code";
        }
    }
    static bool inline is_error_code(string_view code)
    {
        return code[0] == '4' || code[0] == '5';
    }
    std::string urlDecode(const std::string &input)
    {
        std::istringstream iss(input);
        std::ostringstream decoded;
        char ch;
        while (iss.get(ch))
        {
            if (ch == '%' && iss.peek() != '\0')
            {
                // Read the next two characters as hexadecimal
                char hex1, hex2;
                if (iss.get(hex1) && iss.get(hex2))
                {
                    std::istringstream hex_stream(std::string("0x") + hex1 + hex2);
                    int hex_value;
                    if (hex_stream >> std::hex >> hex_value)
                    {
                        decoded.put(static_cast<char>(hex_value));
                    }
                    else
                    {
                        // Invalid hexadecimal encoding, keep '%' and the two characters
                        decoded.put('%');
                        decoded.put(hex1);
                        decoded.put(hex2);
                    }
                }
                else
                {
                    // Incomplete '%' encoding, keep '%'
                    decoded.put('%');
                }
            }
            else
            {
                // Not '%' character, keep it as is
                decoded.put(ch);
            }
        }
        return decoded.str();
    }
    /*
    ** service(业务层):
    **
    ** 此处定义了http业务的处理方法(request->response):
    **  包含: 派发请求到线程池;
    **        调用cgi程序进行数据交互;
    **        构建响应;
    **
    */
private:
    // reactor 入口函数
    //<connection,package> 这里反序列化后 派发给线程池
    int request_handler(connection_t &connection, string &package)
    {
        request req(&connection);
        deserialize(package, req);
        // 此处加入线程池
        _p_thread_pool->put_req(req);
        // 服务器拿到request->线程池
        return 0;
    }
    // 线程处理完业务 取响应回来 序列化
    // 派发给epoll reactor写入输出缓冲区
    // int response_handler()
    // {

    // }
    // 派发给thread pool 线程要做的任务
    virtual void http_service(request &req, response &rsp)
    {
        // 判断连接是否已经删除
        if (req._p_con == nullptr || !_tcp_reactor.is_con_exist(req._p_con))
        {
            log(INFO, "p_con not exits");
            return;
        }
        // 传递连接对象 -- 重要
        rsp._p_con = req._p_con;
        // 解析请求 制定响应策略
        request_type_t req_type = check_request_type(req);
        switch (req_type)
        {
        case request_type_t::STATIC:
        {
            response_file(rsp, req._path);
            break;
        }
        case request_type_t::CGI:
        {
            string content;
            // 获取执行结果和返回正文
            cgi_execer(req, content) ? response_cgi(rsp, std::move(content)) : response_error(rsp, "500");
            break;
        }
        case request_type_t::REDIRECT:
        {
            // 确定 重定向目标
            string redirect_path = req._path.substr(_www_root.size()) + '/';
            if (!req._query_str.empty())
                redirect_path += '?' + req._query_str;
            response_redirect(rsp, "301", redirect_path);
            break;
        }
        default:
        {
            response_error(rsp, "404");
            break;
        }
        }
    }
    // TODO 优化逻辑
    enum class request_type_t
    {
        STATIC,
        CGI,
        REDIRECT,
        BROKEN
    };
    request_type_t check_request_type(request &req)
    {
        struct stat path_st;
        if (stat(req._path.data(), &path_st) != 0)
            return request_type_t::BROKEN;
        if ((S_ISREG(path_st.st_mode) && (path_st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
            return request_type_t::CGI;
        if (S_ISDIR(path_st.st_mode))
            return request_type_t::REDIRECT;
        return request_type_t::STATIC;
    }
    // exec cgi program and get result content by pipe
    // RETURN true for success FALSE for error,will log out debuginfo if ERROR happened;
    bool cgi_execer(request &req, string &content)
    {
        log(INFO, "CGI process");
        log(INFO, to_string(req._body.size()));
        // cgi bin
        string bin = req._path;
        // 站在父进程角度
        int input[2], output[2];
        // 父进程 读input[0]  写output[1];
        // 子进程 读output[0] 写input[1];
        if (pipe(input) || pipe(output))
        {
            log(WARNING, "pipe create error!");
            return false;
        }
        int child = fork();
        if (child != 0)
        {
            if (child > 0)
            {
                log(INFO, string("child running: ") + to_string(child));
                close(input[1]);
                close(output[0]);
            }
            else
            {
                log(ERROR, string("fork failed!:").append(strerror(errno)));
                return false;
            }
        }
        else
        {
            // child
            if (close(input[0]) || close(output[1]) || dup2(output[0], 0) == -1 || dup2(input[1], 1) == -1)
                return false;
            // put env
            string method_env("REQUEST_METHOD=" + req._method);
            string query_string_env("QUERY_STRING=" + req._query_str);
            string content_length_env("CONTENT_LENGTH=" + to_string(req._body.size()));
            string content_type_env("CONTENT_TYPE=" + req._request_handers["Content-Type"]);
            putenv(const_cast<char *>(method_env.data()));
            putenv(const_cast<char *>(query_string_env.data()));
            putenv(const_cast<char *>(content_length_env.data()));
            putenv(const_cast<char *>(content_type_env.data()));
            // execl cgi program
            execl(bin.c_str(), bin.c_str(), nullptr);

            // not reached
            log(FATAL, "execl error");
            close(input[1]);
            return false;
        }

        // send body to cgi
        size_t sent = 0, size = req._body.size();
        while (sent < size)
        {
            // block send
            // 不能用send Socket operation on non-socket errno: 88
            int ret = write(output[1], req._body.c_str() + sent, size - sent);
            if (ret == -1)
            {
                log(ERROR, string("SEND ERROR") + strerror(errno));
                break;
            }
            sent += ret;
        }
        log(INFO, "SEND DONE");

        // 读取cgi处理后的body
        while (1)
        {
            const size_t buffer_size = 1024;
            char buffer[buffer_size];
            memset(buffer, 0, buffer_size);
            ssize_t read_size = read(input[0], buffer, buffer_size);
            if (read_size <= 0)
                break;
            content.append(buffer);
        }
        close(input[0]);
        close(output[1]);
        int status = 0;
        pid_t dead_child = wait(&status);
        log(INFO, string("buryed child :") + to_string(dead_child));
        // 如果正常退出
        if (WIFEXITED(status))
        {
            // 根据退出码构建响应
            int ret = WEXITSTATUS(status);
            if (ret == 0)
                return true;
        }
        return false;
    }
    int response_error(response &rsp, string code)
    {
        // 首行 版本 码 描述
        // kv 格式 重定向 正文长度
        // content 有/无
        rsp._version = "HTTP/1.1";
        rsp._code = code;
        rsp._status_info = code_to_info(code);
        if (rsp._status_info.empty())
        {
            code = "500";
            rsp._status_info = code_to_info(code);
        }
        string content("<!DOCTYPE html><html><h1>");
        content.append(code + ":" + rsp._status_info);
        content.append("</h1></html>");
        rsp._body = std::move(content);
        rsp._reponse_handers["Content-Type"] = "text/html";
        rsp._reponse_handers["Content-Length"] = to_string(rsp._body.size());
        return stoi(rsp._code);
    }
    int response_file(response &rsp, string file_path)
    {
        // 首行
        rsp._version = "HTTP/1.1";
        rsp._code = "200";
        rsp._status_info = code_to_info(rsp._code);
        // 打开文件 获取文件信息
        int fd = open(file_path.c_str(), O_RDONLY);
        if (fd < 0)
        {
            log(ERROR, "cant open sendfile");
            return response_error(rsp, "404");
        }
        // 文件类型
        size_t ext_pos = file_path.find_last_of('.');
        string file_extention = (ext_pos == string::npos ? ".html" : file_path.substr(ext_pos));
        // 文件大小
        struct stat buf;
        fstat(fd, &buf);
        size_t file_size = buf.st_size;
        // 填充首部kv信息
        rsp._reponse_handers["Content-Type"] = ext_to_type(file_extention);
        rsp._reponse_handers["Content-Length"] = to_string(file_size);
        // 调用sendfile
        rsp._file_fd = fd;
        rsp._file_size = file_size;
        return 200;
    }
    int response_content(response &rsp, string code, string &&content = "", string content_type = "text/html")
    {
        rsp._version = "HTTP/1.1";
        rsp._code = code;
        rsp._status_info = code_to_info(code);
        if (rsp._status_info.empty())
        {
            code = "200";
            rsp._status_info = code_to_info(code);
        }
        rsp._body = std::forward<string>(content);
        rsp._reponse_handers["Content-Type"] = content_type;
        rsp._reponse_handers["Content-Length"] = to_string(rsp._body.size());
        return stoi(rsp._code);
    }
    int response_cgi(response &rsp, string &&cgi_out = "")
    {
        // default first line, might be modified base on cgi's output.
        rsp._version = "HTTP/1.1";
        rsp._code = "200";
        rsp._status_info = code_to_info(rsp._code);
        try // in blow contianes some string's methods
        {
            // prase cgi-out handers
            size_t sep_pos = cgi_out.find(SEP);
            size_t header_end_pos = sep_pos == string::npos ? 0 : sep_pos + strlen(CRLF);
            size_t content_start_pos = header_end_pos == 0 ? header_end_pos : header_end_pos + strlen(CRLF);
            parse_head_kv(rsp._reponse_handers, cgi_out.substr(0, header_end_pos));
            if (rsp._reponse_handers.count("Status"))
            {
                string code_info = rsp._reponse_handers.at("Status");
                size_t div_pos = code_info.find(' ');
                rsp._code = code_info.substr(0, div_pos);
                rsp._status_info = code_info.substr(div_pos + 1);
            }
            rsp._body = std::forward<string>(cgi_out.substr(header_end_pos));
            rsp._reponse_handers["Content-Length"] = to_string(rsp._body.size());
            return stoi(rsp._code);
        }
        catch (std::exception &e)
        {
            log(ERROR, e.what());
            return response_error(rsp, "500");
        }
    }
    int response_redirect(response &rsp, string code, string url)
    {
        rsp._version = "HTTP/1.1";
        rsp._code = code;
        rsp._status_info = code_to_info(code);
        if (rsp._status_info.empty())
        {
            code = "301";
            rsp._status_info = code_to_info(code);
        }
        rsp._body.clear();
        rsp._reponse_handers["Location"] = url;
        rsp._reponse_handers["Content-Length"] = "0";
        return stoi(rsp._code);
    }

private:
    // tcp reactor -> IO
    tcp_reactor_t _tcp_reactor;
    // thread_pool->service
    thread_pool_t<request, response> *_p_thread_pool;
    // web root
    string _www_root;
    string _home_page;
};
